<template>
	<view>
		<view class="waterfall-box h-flex-x h-flex-2" v-if="showList">
			<view v-for="(parent,pIndex) in dynamicList" :key="parent.id">
				<view v-for="(item,index) in parent.list" :key="item._render_id" class="list-item"
					:class="{'show': showPage > item._current_page }">
					<helang-waterfall-item :params="item" :place="item.place" :index="index"
						@height="onHeight" :parentPlace="item.parentPlace"
						@click="onClick"></helang-waterfall-item>
				</view>
			</view>
		</view>

		<slot name="default"></slot>
	</view>
</template>

<script>
	import helangWaterfallItem from "./waterfall-item.vue"

	export default {
		name: "helangWaterfallList",
		options: {
			virtualHost: true
		},
		components: {
			"helang-waterfall-item": helangWaterfallItem
		},
		props: {
			// 组件状态
			status: {
				type: String,
				default: ''
			},
			// 待渲染的数据
			list: {
				type: Array,
				default () {
					return [];
				}
			},
			// 重置列表，设置为 true 时，瀑布流会自动重新渲染列表
			reset: {
				type: Boolean,
				default: false
			},
			colums: {
				type: Number,
				default: 2
			}
		},
		watch: {
			"$props.status": {
				handler(newValue, oldValue) {
					// 状态变更为 加载成功 时，执行瀑布流数据渲染	
					if (newValue == 'success') {
						this.startRender();
					} else if (!this.showList) {
						this.resetData();
					}
				},
				immediate: false
			}
		},
		computed: {
			showList() {
				return !["fail", "empty"].includes(this.$props.status);
			}
		},
		data() {
			return {
				// 待渲染列表
				awaitRenderList: [],
				// 当前展示页码数据
				showPage: 1,
				dynamicList: [],
				dynamicHeightList: []
			}
		},
		created() {
			for (let i = 0; i < this.colums; i++) {
				this.dynamicList.push({
					id: new Date().getTime() + i,
					list: [],
					p: 1
				})
				this.dynamicHeightList.push(0)
			}
		},
		methods: {
			// 监听高度变化
			onHeight(height, tag) {
				/**
				 * 这个为实际渲染后 CSS 中 margin-buttom 的值，本示例默认为20rpx
				 * 用于解决实际渲染后因为数据条数关系，高度差计算偏差的问题
				 * */
				let marginBottom = uni.upx2px(20);
				//tag是标记每一个选然后好给对应列记录累加高度
				this.dynamicHeightList[tag] = this.dynamicHeightList[tag] + (height + marginBottom);
				this.renderList();
			},
			// 组件点击事件
			onClick(index, place, parentPlace) {
				this.$emit("click", this.dynamicList[place].list[index], place, parentPlace);
			},
			// 渲染列表，这里实现瀑布流的左右分栏
			renderList() {
				// 待渲染长度为 0 时表示已渲染完成
				if (this.awaitRenderList.length <= 0) {
					this.showPage++;
					let maxIndex = this.dynamicHeightList.indexOf(Math.max(...this.dynamicHeightList))
					this.$emit("done",this.dynamicHeightList[maxIndex]);
					// 为防止 js 数值类型最大值溢出，当高度值大于 1亿时重置高度
					if (maxIndex != -1 && this.dynamicHeightList[maxIndex] > 100000000) {
						uni.showToast({
							icon: "error",
							title: "内存溢出！"
						})
					}
					return;
				}
				let minIndex = this.dynamicHeightList.indexOf(Math.min(...this.dynamicHeightList))
				let dynamicNumList = this.dynamicList.map(item => item.list.length)
				let total = dynamicNumList.reduce((last, current) => {
					return last + current
				}, 0)
				let item = {
					...this.awaitRenderList.splice(0, 1)[0],
					// 当前数据添加当前页面标识
					_current_page: this.showPage,
					// 当前数据添加一个渲染id，解决 v-for 重复会出现不执行 load 的 BUG
					_render_id: new Date().getTime(),
					place: minIndex,
					parentPlace: total
				};

				//找出最低高度位置
				this.dynamicList[minIndex].list.push(item)
			},
			// 重置数据
			resetData() {
				this.dynamicHeightList = []
				this.dynamicList = []
				for (let i = 0; i < this.colums; i++) {
					this.dynamicList.push({
						id: new Date().getTime() + i,
						list: []
					})
					this.dynamicHeightList.push(0)
				}
				this.awaitRenderList = [];
				// 当前展示页码数据
				this.showPage = 1;
			},
			// 启动渲染
			startRender() {
				if (!this.showList) {
					this.resetData();
					return;
				}

				if (!this.$props.list || this.$props.list.length < 1) {
					console.log('河浪瀑布流插件提示：当前数据为空，不会触发列表渲染');
					return;
				}

				// 若本次渲染为 重置 则先恢复组件的默认参数
				if (this.$props.reset) {
					this.resetData();
				}
				this.awaitRenderList = [...this.$props.list];
				this.renderList();
			}
		}
	}
</script>

<style lang="scss" scoped>
	.waterfall-box {
		// padding: 20rpx 10rpx;
		// box-sizing: border-box;

		>view {
			padding: 0 10rpx;
		}

		.list-item {
			margin-bottom: 0;
			// 设置透明，默认是可视的
			opacity: 0;
			// 默认超出隐藏，不影响加载中的文字显示效果
			overflow: hidden;
			height: 0;

			&.show {
				margin-bottom: 20rpx;
				opacity: 1;
				overflow: auto;
				height: auto;
			}
		}
	}

	.h-flex-x {
		display: flex;
		flex-direction: row;
		flex-wrap: nowrap;
		justify-content: flex-start;
		align-items: flex-start;
		align-content: flex-start;

		&.h-flex-2 {
			>view {
				width: 50%;
			}
		}
	}
</style>